package com.lin.controller;

import cn.hutool.core.util.ObjectUtil;
import com.lin.common.RedisCache;
import com.lin.domain.common.AjaxResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/upload")
public class UploadController {
    @Resource
    private RedisCache redisCache;
    private final long CHUNK_SIZE = 1024 * 1024 * 10; //10M
    private final String CHUNK_PREFIX = "chunk_"; //已经分片集合
    private final String UPLOAD_ISOK_PREFIX = "upload_isok_"; //判断上传是否完成

    /**
     * 分片文件上传
     * @param file 文件
     * @param chunkIndex 分片下标
     * @param md5 md5
     * @param totalFileSize 文件总大小
     * @param fileName 文件名
     */
    @PostMapping("/shard")
    public AjaxResult shardUpload(@RequestParam MultipartFile file, @RequestParam Integer chunkIndex,
                                  @RequestParam String md5, @RequestParam Long totalFileSize,
                                  @RequestParam String fileName) throws Exception{
        // 存放文件目录
        String dirPath = System.getProperty("user.dir") + "/file/"+md5+"/";
        File dirFile = new File(dirPath);
        if(!dirFile.exists()){
            dirFile.mkdir();
        }
        File tempFile = new File(dirPath + fileName);
        RandomAccessFile rw = new RandomAccessFile(tempFile, "rw");
        // 定位到分片的偏移量
        rw.seek(CHUNK_SIZE * chunkIndex);
        // 写入分片数据
        rw.write(file.getBytes());
        // 关闭流
        rw.close();
        // 读取已经分片集合
        List<Object> hasChunkList;
        String hasChunkKey = CHUNK_PREFIX + md5;
        if(redisCache.hasKey(hasChunkKey)){
            hasChunkList = redisCache.getCacheList(hasChunkKey);
        } else {
            hasChunkList = new ArrayList<>();
        }
        hasChunkList.add(chunkIndex);
        // 将最新的分片下标更新到Redis中
        redisCache.addCacheListOne(hasChunkKey,chunkIndex);
        // 判断是否上传完成
        int totalNeedChunks = (int) Math.ceil((double) totalFileSize / CHUNK_SIZE);
        // 总共需要的分片数 和 已经分片上传的数量相等 则上传完成
        boolean isOk = totalNeedChunks == hasChunkList.size();
        if(isOk){
            redisCache.setCacheObject(UPLOAD_ISOK_PREFIX + md5, true);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("hasChunkList",hasChunkList);
        ajax.put("isOk",isOk);
        return ajax;
    }

    @GetMapping("/check/{md5}")
    public AjaxResult check(@PathVariable("md5") String md5) {
        AjaxResult ajax = AjaxResult.success();
        Object isOk = redisCache.getCacheObject(UPLOAD_ISOK_PREFIX + md5);
        if(ObjectUtil.isNotNull(isOk)){ //已经上传过,秒传
            ajax.put("isOk",true);
            return ajax;
        }
        List<Object> haveList = redisCache.getCacheList(CHUNK_PREFIX + md5); //正在上传的分片集合
        if(ObjectUtil.isNull(haveList)){
            haveList = new ArrayList<>();
        }
        ajax.put("haveList",haveList);
        return ajax;
    }
}
